package com.example.springboot.controller;

import com.example.springboot.vo.ErrorVO;
import com.example.springboot.vo.UserVO;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 对requestBody参数校验
 * <p>
 * <p>
 * @author Zhang.Z
 * @version 2025-09-20
 */

@RestController
public class ValidController {


    /**
     * 手动验证
     * <p> 使用场景不在 Spring MVC 控制器里，或者需要手动验证对象（比如服务层、定时任务）
     * <p> 通过工厂方法验证，此验证可以抽取成公共方法。
     * <code>
     *     <pre>
     *   static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
     *
     *   static <T> List<ErrorVO> validate(T object) {
     *         Set<ConstraintViolation> violations = validator.validate(object);
     *         List<ErrorVO> errors = violations.stream()
     *         .map(v -> new ErrorVO(v.getPropertyPath().toString(), v.getMessage()))
     *         .collect(Collectors.toList());
     *         return List;
     *   }
     *       </pre>  </code>
     */
    @RequestMapping(value = "/test/valid1")
    public String testValid1(@RequestBody UserVO vo) throws JsonProcessingException {
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        //执行验证
        Set<ConstraintViolation<UserVO>> validate = validator.validate(vo);
        if (!CollectionUtils.isEmpty(validate)) {
            List<ErrorVO> errors = validate.stream()
                    .map(v -> new ErrorVO(v.getPropertyPath().toString(), v.getMessage()))
                    .collect(Collectors.toList());

            final ObjectMapper m = new ObjectMapper();
            m.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
            String result = m.writeValueAsString(errors);

            return result;
        }


        return "验证通过";
    }

    /**
     * MVC 自动验证，通过 @Valid 和BindingResult进行验证。
     * <p>
     * @param vo
     * @param bindingResult
     * @return
     */
    @RequestMapping(value = "/test/valid2")
    public String testValid2(@RequestBody @Valid UserVO vo, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {

            return bindingResult.getFieldError().getField() + " : " + bindingResult.getFieldError().getDefaultMessage();
        }

        return "验证通过";
    }
}
